package com.sora.sora.security.login.service.impl;

import com.google.code.kaptcha.Constants;
import com.sora.sora.common.exception.ApiException;
import com.sora.sora.common.model.entity.UserEntity;
import com.sora.sora.common.utils.StringUtils;
import com.sora.sora.security.authorise.mapper.RoleMapper;
import com.sora.sora.security.login.mapper.RegisterMapper;
import com.sora.sora.security.login.model.param.RegisterParam;
import com.sora.sora.security.login.service.LoginService;
import com.sora.sora.security.login.service.RegisterService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.time.Duration;
import java.util.Date;
import java.util.Objects;

@Service("registerService")
public class RegisterServiceImpl implements RegisterService {

    @Resource
    LoginService loginService;

    @Resource
    RegisterMapper registerMapper;

    @Resource
    RedisTemplate<String, String> redisTemplate;

    @Resource
    PasswordEncoder passwordEncoder;

    @Resource
    StringUtils stringUtils;

    private boolean emailExist(String email) {
        return registerMapper.emailExist(email) != null;
    }

    private boolean userExist(String name) { return registerMapper.nameExist(name) != null; }

    @Override
    public boolean register(RegisterParam registerParam) {

        String name = registerParam.getName();
        String email = registerParam.getEmail();
        String verifyCode = registerParam.getVerifyCode();

        if (emailExist(email)) {
            throw new ApiException("邮箱已经存在");
        } else if (userExist(name)) {
            throw new ApiException("昵称已存在");
        }

        if (!stringUtils.nameCheck(name)) {
            throw new ApiException("昵称含有非法字符");
        } else if (!stringUtils.passwordCheck(registerParam.getPassword())) {
            throw new ApiException("密码含有非法字符");
        }

        String code = redisTemplate.opsForValue().get(email);

        if (code == null) {
            throw new ApiException("邮箱验证码已过期");
        } else if (!verifyCode.equals(code)) {
            throw new ApiException("验证码错误");
        }

        UserEntity userEntity = new UserEntity(name, passwordEncoder.encode(registerParam.getPassword()), email, new Date());

        int i = registerMapper.register(userEntity);
        return i > 0;
    }

    @Override
    public boolean sysRegister(RegisterParam registerParam) {
        String name = registerParam.getName();
        String email = registerParam.getEmail();

        if (emailExist(email)) {
            throw new ApiException("邮箱已经存在");
        } else if (userExist(name)) {
            throw new ApiException("昵称已存在");
        }

        if (!stringUtils.nameCheck(name)) {
            throw new ApiException("昵称含有非法字符");
        } else if (!stringUtils.passwordCheck(registerParam.getPassword())) {
            throw new ApiException("密码含有非法字符");
        }

        UserEntity userEntity = new UserEntity(name, passwordEncoder.encode(registerParam.getPassword()), email, new Date());

        int i = registerMapper.register(userEntity);
        return i > 0;
    }

    @Override
    public boolean saveCode(String sessionId, String code) {
        System.out.println(redisTemplate.hasKey("123"));
        Duration expire = Duration.ofMinutes(5);
        if (Boolean.TRUE.equals(redisTemplate.hasKey(sessionId))) {
            Long remainExpireTime = redisTemplate.getExpire(sessionId) * 1000;  // 将单位化为毫秒，和其它变量单位相同
            System.out.println(remainExpireTime);
            // 允许获取验证码的间隔是100s
            Long callTime = Duration.ofSeconds(100).toMillis();
            if (expire.toMillis() - remainExpireTime <= callTime) {
                // 如果调用时间小于100s则禁止调用
                return false;
            }
            // 大于100s允许调用新的验证码
        }

        redisTemplate.opsForValue().set(sessionId, code, expire);
        return true;
    }

    @Override
    public boolean checkCode(String sessionId, String code) {
        if (Objects.equals(redisTemplate.opsForValue().get(sessionId), code)) {
            // 重新设置过期时间，用于之后调用发送注册邮件接口时的检验
            redisTemplate.expire(sessionId, Duration.ofMinutes(10));
            return true;
        }
        return false;
    }
}
